package com.Steganography;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 隐写术，将内容写到图像中，并且可以提出来
 */
public class Steganography {

    /**
     * 隐藏信息到 图像中
     * @param inputImagePath 输入文件
     * @param outputImagePath 输出文件
     * @param secretMessage
     */
    public static void hideTextIntoImage(String inputImagePath, String outputImagePath, String secretMessage) {
        try {
            // 读取输入图像
            BufferedImage image = ImageIO.read(new File(inputImagePath));
            int width = image.getWidth();
            int height = image.getHeight();
            int totalPixels = width * height;
            // 将秘密消息转换为二进制字符串，并加上终止符
            String binaryMessage = messageToBinary(secretMessage) + "1111111111111110"; // 终止符用于标记消息结束

            if (binaryMessage.length() > totalPixels) {
                System.out.println("Error: Message is too large to be hidden in the image.");
                return;
            }

            int bitIndex = 0;
            for (int row = 0; row < height && bitIndex < binaryMessage.length(); row++) {
                for (int col = 0; col < width && bitIndex < binaryMessage.length(); col++) {
                    int rgb = image.getRGB(col, row);
                    int r = (rgb >> 16) & 0xff;
                    int g = (rgb >> 8) & 0xff;
                    int b = rgb & 0xff;

                    // 修改红色通道的最低有效位
                    r = setBit(r, 0, binaryMessage.charAt(bitIndex++) == '1');

                    // 设置新的像素值
                    rgb = (r << 16) | (g << 8) | b;
                    image.setRGB(col, row, rgb);
                }
            }

            // 输出修改后的图像
            ImageIO.write(image, "png", new File(outputImagePath));
            System.out.println("Message hidden successfully!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String messageToBinary(String message) {
        StringBuilder binaryString = new StringBuilder();
        for (char c : message.toCharArray()) {
            StringBuilder binaryChar = new StringBuilder(Integer.toBinaryString(c));
            while (binaryChar.length() < 8) {
                binaryChar.insert(0, "0");
            }
            binaryString.append(binaryChar);
        }
        return binaryString.toString();
    }

    private static int setBit(int value, int position, boolean set) {
        if (set) {
            return value | (1 << position);
        } else {
            return value & ~(1 << position);
        }
    }

    public static String extractTextFromImage(String imagePath) {
        try {
            BufferedImage image = ImageIO.read(new File(imagePath));
            int width = image.getWidth();
            int height = image.getHeight();

            StringBuilder binaryMessage = new StringBuilder();
            for (int row = 0; row < height; row++) {
                for (int col = 0; col < width; col++) {
                    int rgb = image.getRGB(col, row);
                    int r = (rgb >> 16) & 0xff;

                    // 获取红色通道的最低有效位
                    binaryMessage.append((r & 1) == 1 ? '1' : '0');
                }
            }

            // 转换为字符串并检查终止符
            return binaryToString(binaryMessage.toString());
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static String binaryToString(String binaryMessage) {
        String[] bytes = binaryMessage.split("(?<=\\G.{8})");
        StringBuilder message = new StringBuilder();
        for (String byteStr : bytes) {
            if ("1111111111111110".startsWith(byteStr)) { // 检查是否到达了终止符
                break;
            }
            int charCode = Integer.parseInt(byteStr, 2);
            message.append((char) charCode);
        }
        return message.toString();
    }

    public static void main(String[] args) throws IOException {
        String input = "C:\\Users\\wy\\Desktop\\新建文件夹\\file.png";
        String output = "C:\\Users\\wy\\Desktop\\新建文件夹\\file2.png";
        String s1 = readFileToString("C:\\Users\\wy\\Desktop\\11.txt");
        hideTextIntoImage(input,output,s1);
        String s = extractTextFromImage(output);
        System.out.println(s);
    }
    public static String readFileToString(String filePath) throws IOException {
        // 使用 Paths.get() 方法获取文件路径
        Path path = Paths.get(filePath);
        // 读取所有行到一个字符串
        String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
        return content;
    }
}